#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/un.h>

/**
 * Linux文件类型有7种，还有一种套接字文件， 
 * 使用socket实现通过套接字文件实现进程之间通信
 */

//server 实现接收客户端数据，收到以后发送出去


// 可以按照tcp ，udp 来写，这里说tcp 一般用 
int main(int argc, const char* argv[])
{
    // AF_LOCAL ： 本地套接字
    // SOCK_STREAM: tcp方式
    int lfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if(lfd == -1)
    {
        perror("socket error");
        exit(1);
    }
//文件有7种类型， 管道是p,  ls -l 查看，  套接字：s   套接字和管道都是伪文件，永远是0大小在磁盘上，存在内核的缓冲区里面
    // 如果套接字文件存在, 删除套接字文件
    unlink("server.sock");

    // 绑定
    struct sockaddr_un serv;
    serv.sun_family = AF_LOCAL;
//     struct sockaddr_un
//   {
//     __SOCKADDR_COMMON (sun_);
//     char sun_path[108];		/* Path name. 本地套接字路径 */
//   };
    strcpy(serv.sun_path, "server.sock");
    int ret = bind(lfd, (struct sockaddr*)&serv, sizeof(serv));  //绑定成功以后server.sock会自动创建出来文件
    if(ret == -1)
    {
        perror("bind error");
        exit(1);
    }
     
    // 监听， 等待对方请求 
    ret = listen(lfd, 36);
    if(ret == -1)
    {
        perror("listen error");
        exit(1);
    }


    // 等待接收连接请求
    struct sockaddr_un client;
    socklen_t len = sizeof(client);
    int cfd = accept(lfd, (struct sockaddr*)&client, &len);
    if(cfd == -1)
    {
        perror("accept error");
        exit(1);
    }
    printf("======client bind file: %s\n", client.sun_path);
     
    // 通信
    while(1)
    {
        char buf[1024] = {0};
        int recvlen = recv(cfd, buf, sizeof(buf), 0);
        if(recvlen == -1)
        {
            perror("recv error");
            exit(1);
        }
        else if(recvlen == 0)
        {
            printf("clietn disconnect ....\n");
            close(cfd);
            break;
        }
        else
        {
            printf("recv buf: %s\n", buf);
            send(cfd, buf, recvlen, 0);
        }
    }
    close(cfd);
    close(lfd);
    
    return 0;
}
